#include "Lamp2.h"

#ifdef NULL
#  undef NULL
#  define NULL 0
#else
#  define NULL 0
#endif

namespace UTSS
{
	Tuint32 CLamp::m_nCount = 0;

	CLamp::CLamp( eLampColor nColor )
		: m_nColor( nColor )
		, m_nID( ++m_nCount )
	{

	}

	
	/////////////////////////////////////////////////////////////
	
	Tuint32 CLampInfo::m_nCount = 0;

	CLampInfo::CLampInfo()
		: m_nTime( NormalTime )
		, m_nInfo( specific )
		, m_nID( ++m_nCount )
		, m_bEnable( false )
	{
		
	}
		
	CLampInfo::CLampInfo( ePhaseInfo nInfo )
		: m_nTime( NormalTime )
		, m_nInfo( nInfo )
		, m_nID( ++m_nCount )
		, m_bEnable( false )
	{

	}

	CLampInfo::CLampInfo( Tuint32 nTime, ePhaseInfo nInfo )
		: m_nTime( nTime )
		, m_nInfo( nInfo )
		, m_nID( ++m_nCount )
		, m_bEnable( false )
	{
		
	}

	CLampInfo::~CLampInfo()
	{
		Stop();
	}

	void CLampInfo::SetLamp()
	{
		switch ( m_nInfo ) 
		{
		case stop :
			m_cLamp[0].SetColor( CLamp::red );
			m_cLamp[1].SetColor( CLamp::red );
			m_cLamp[2].SetColor( CLamp::red );
			break;
		case stright :
			m_cLamp[0].SetColor( CLamp::red );
			m_cLamp[1].SetColor( CLamp::green );
			m_cLamp[2].SetColor( CLamp::red );
			break;
		case turn :
			m_cLamp[0].SetColor( CLamp::green );
			m_cLamp[1].SetColor( CLamp::red );
			m_cLamp[2].SetColor( CLamp::red );
			break;
		case cross :
			m_cLamp[0].SetColor( CLamp::green );
			m_cLamp[1].SetColor( CLamp::red );
			m_cLamp[2].SetColor( CLamp::green );
			break;
		default :
			break;
		}
	}

	void CLampInfo::ChgLamp()
	{
		if ( !IsEnable() )
			return;

		switch ( m_nInfo )
		{
		case stop :
			m_nInfo = cross;
			SetLamp();
			break;
		case cross :
			m_nInfo = turn;
			SetLamp();
			break;
		case turn :
			m_nInfo = stright;
			SetLamp();
			break;
		case stright :
			m_nInfo = stop;
			SetLamp();
			break;
		default :
			break;
		}
	}

	void CLampInfo::Run()
	{
		if ( !IsEnable() )	
			MakeEnable();

		while ( 1 ) 
		{
			if ( !IsEnable() )
				return;
			ChgLamp();
			std::cout << *this << std::endl;
		}
	}

	void CLampInfo::Stop()
	{
		if ( IsEnable() )
		{
			MakeUnable();
		}
	}

	std::ostream & operator<< ( std::ostream & o, CLampInfo & lo )
	{
		char str[4][10];
		int i;
		for ( i = 0; i < 3; i++ )
		{
			switch ( lo.m_cLamp[i].GetColor() )
			{
			case CLamp::red :
				strcpy( str[i], "red" );
				break;
			case CLamp::green :
				strcpy( str[i], "green" );
				break;
			case CLamp::yellow :
				strcpy( str[i], "yellow" );
			default :
				break;
			}
		}

		switch ( lo.m_nID )
		{
		case CLampInfo::cross :
			strcpy( str[3], "cross" );
			break;
		case CLampInfo::stright :
			strcpy( str[3], "stright" );
			break;
		case CLampInfo::stop :
			strcpy( str[3], "stop" );
			break;
		case CLampInfo::turn :
			strcpy( str[3], "turn" );
			break;
		default :
			break;
		}

		o << "The "  << lo.m_nID << "th " << " lampinfo is : " 
			<< 	str[3] 
			<< ". And current color is : " 
			<< str[0] << " " << str[1] << " " << str[2];
		return o;
	}

	/////////////////////////////////////////////////////////////

	CPhaseMgr * CPhaseMgr::init_phase_mgr( CPhaseMgr * pr )
	{
		if ( pr == 0 ) 
		{
			pr = new CPhaseMgr;
		}
		return pr;
	}
	
	CPhaseMgr::CPhaseMgr()
		: m_nUsed( 0 )
		, m_nCount( 0 )
	{

	}
	

	CPhaseMgr::~CPhaseMgr()
	{
		m_lLamps.clear();

		m_nCount	= 0;
		m_nUsed		= 0;
	}

	typedef std::list<CLampInfo*> CList;
	CList & CPhaseMgr::AddLampInfo( CLampInfo * lo )
	{
		CList::iterator it;
		bool bAddFlag = false;
		Tuint32 nID   = lo->GetID();

		for ( it = m_lLamps.begin(); it != m_lLamps.end(); ++it )
		{
			if ( (*it)->GetID() != nID ) 
			{
				bAddFlag = true;
			}
			else
			{
				bAddFlag = false;
			}
		}
		if ( bAddFlag )
		{
			m_lLamps.push_back( lo );
			++m_nCount;
		}
		
		return m_lLamps;
	}

	Tuint32 CPhaseMgr::CheckUsedCnt() 
	{
		CList::iterator it;
		Tuint32 ret = 0;

		for ( it = m_lLamps.begin(); it != m_lLamps.end(); ++it )
		{
			if ( (*it)->IsEnable() )
				ret++;
		}
		
		return ret;
	}


	/////////////////////////////////////////////////////////////////
	
	

	CCross::CCross( Tuint32 nRoadCnt )
		: m_nRoadCnt( nRoadCnt )
		, m_pRoad( new ROADINFO[nRoadCnt] )
	{
	
	}

	CCross::CCross( ROADINFO *ro, Tuint32 nRoadCnt )
		: m_nRoadCnt ( nRoadCnt )
		, m_pRoad( ro )
	{

	}

	CCross::~CCross()
	{
		delete[] m_pRoad;
	}
	
	void CCross::Init()
	{
		CLampInfo::ePhaseInfo info[4];
		info[0] = CLampInfo::stop;
		info[1] = CLampInfo::cross;
		info[2] = CLampInfo::turn;
		info[3] = CLampInfo::stright;
		
		for ( Tuint32 i = 0; i < m_nRoadCnt; ++i )
		{
			m_pRoad[i].MakeEnable();
			m_pRoad[i].SetDirection( info[i] );
		}
	}


	void CCross::Run()
	{
		Init();
		while ( 1 )
		{
#ifdef NDEBUG
			Sleep( m_pRoad[i].GetRoadTime() * 1000 );
#endif
			for ( Tuint32 j = 0; j < m_nRoadCnt; ++j )
			{
				m_pRoad[j].GetRoadInfo();
				if ( m_pRoad[j].IsEnable() )
				{
					m_pRoad[j].ChgLamp();
					std::cout << m_pRoad[j].GetLamp() << std::endl;
				} 
			} 
		} 
	} 


}
